From f3468348d9d2007185349925537765a33cc295d1 Mon Sep 17 00:00:00 2001 From: James Bendig Date: Tue, 7 Feb 2017 18:20:21 -0600 Subject: [PATCH] Added required_features for issue #1570. Based on PR #2056 by @tsurai and PR #2325 by @JanLikar --- src/cargo/core/manifest.rs | 19 +- src/cargo/ops/cargo_compile.rs | 65 +++- src/cargo/util/toml.rs | 14 +- tests/required-features.rs | 565 +++++++++++++++++++++++++++++++++ 4 files changed, 640 insertions(+), 23 deletions(-) create mode 100644 tests/required-features.rs diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 2354eadfe..6c71cd9b9 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -185,6 +185,7 @@ pub struct Target { kind: TargetKind, name: String, src_path: PathBuf, + required_features: Option>, tested: bool, benched: bool, doc: bool, @@ -305,6 +306,7 @@ impl Target { kind: TargetKind::Bin, name: String::new(), src_path: src_path, + required_features: None, doc: false, doctest: false, harness: true, @@ -326,10 +328,12 @@ impl Target { } } - pub fn bin_target(name: &str, src_path: PathBuf) -> Target { + pub fn bin_target(name: &str, src_path: PathBuf, + required_features: Option>) -> Target { Target { kind: TargetKind::Bin, name: name.to_string(), + required_features: required_features, doc: true, ..Target::with_path(src_path) } @@ -349,7 +353,8 @@ impl Target { pub fn example_target(name: &str, crate_targets: Vec, - src_path: PathBuf) -> Target { + src_path: PathBuf, + required_features: Option>) -> Target { let kind = if crate_targets.is_empty() { TargetKind::ExampleBin } else { @@ -359,24 +364,29 @@ impl Target { Target { kind: kind, name: name.to_string(), + required_features: required_features, benched: false, ..Target::with_path(src_path) } } - pub fn test_target(name: &str, src_path: PathBuf) -> Target { + pub fn test_target(name: &str, src_path: PathBuf, + required_features: Option>) -> Target { Target { kind: TargetKind::Test, name: name.to_string(), + required_features: required_features, benched: false, ..Target::with_path(src_path) } } - pub fn bench_target(name: &str, src_path: PathBuf) -> Target { + pub fn bench_target(name: &str, src_path: PathBuf, + required_features: Option>) -> Target { Target { kind: TargetKind::Bench, name: name.to_string(), + required_features: required_features, tested: false, ..Target::with_path(src_path) } @@ -385,6 +395,7 @@ impl Target { pub fn name(&self) -> &str { &self.name } pub fn crate_name(&self) -> String { self.name.replace("-", "_") } pub fn src_path(&self) -> &Path { &self.src_path } + pub fn required_features(&self) -> Option<&Vec> { self.required_features.as_ref() } pub fn kind(&self) -> &TargetKind { &self.kind } pub fn tested(&self) -> bool { self.tested } pub fn harness(&self) -> bool { self.harness } diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index ec13b2a2e..27b861029 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -22,7 +22,8 @@ //! previously compiled dependency //! -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; +use std::default::Default; use std::path::PathBuf; use std::sync::Arc; @@ -187,7 +188,8 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>, } } else { let root_package = ws.current()?; - generate_targets(root_package, profiles, mode, filter, release)?; + let all_features = resolve_with_overrides.features(root_package.package_id()); + generate_targets(root_package, profiles, mode, filter, all_features, release)?; pkgids.push(root_package.package_id()); }; @@ -204,8 +206,9 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>, panic!("`rustc` and `rustdoc` should not accept multiple `-p` flags") } (Some(args), _) => { + let all_features = resolve_with_overrides.features(to_builds[0].package_id()); let targets = generate_targets(to_builds[0], profiles, - mode, filter, release)?; + mode, filter, all_features, release)?; if targets.len() == 1 { let (target, profile) = targets[0]; let mut profile = profile.clone(); @@ -218,8 +221,9 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>, } } (None, Some(args)) => { + let all_features = resolve_with_overrides.features(to_builds[0].package_id()); let targets = generate_targets(to_builds[0], profiles, - mode, filter, release)?; + mode, filter, all_features, release)?; if targets.len() == 1 { let (target, profile) = targets[0]; let mut profile = profile.clone(); @@ -233,8 +237,9 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>, } (None, None) => { for &to_build in to_builds.iter() { + let all_features = resolve_with_overrides.features(to_build.package_id()); let targets = generate_targets(to_build, profiles, mode, - filter, release)?; + filter, all_features, release)?; package_targets.push((to_build, targets)); } } @@ -313,6 +318,7 @@ fn generate_targets<'a>(pkg: &'a Package, profiles: &'a Profiles, mode: CompileMode, filter: &CompileFilter, + features: Option<&HashSet>, release: bool) -> CargoResult> { let build = if release {&profiles.release} else {&profiles.dev}; @@ -325,13 +331,13 @@ fn generate_targets<'a>(pkg: &'a Package, CompileMode::Doc { .. } => &profiles.doc, CompileMode::Doctest => &profiles.doctest, }; - match *filter { + let mut targets = match *filter { CompileFilter::Everything => { match mode { CompileMode::Bench => { - Ok(pkg.targets().iter().filter(|t| t.benched()).map(|t| { + pkg.targets().iter().filter(|t| t.benched()).map(|t| { (t, profile) - }).collect::>()) + }).collect::>() } CompileMode::Test => { let deps = if release { @@ -352,16 +358,16 @@ fn generate_targets<'a>(pkg: &'a Package, base.push((t, deps)); } } - Ok(base) + base } CompileMode::Build | CompileMode::Check => { - Ok(pkg.targets().iter().filter(|t| { + pkg.targets().iter().filter(|t| { t.is_bin() || t.is_lib() - }).map(|t| (t, profile)).collect()) + }).map(|t| (t, profile)).collect() } CompileMode::Doc { .. } => { - Ok(pkg.targets().iter().filter(|t| t.documented()) - .map(|t| (t, profile)).collect()) + pkg.targets().iter().filter(|t| t.documented()) + .map(|t| (t, profile)).collect() } CompileMode::Doctest => { if let Some(t) = pkg.targets().iter().find(|t| t.is_lib()) { @@ -370,7 +376,7 @@ fn generate_targets<'a>(pkg: &'a Package, } } - Ok(Vec::new()) + Vec::new() } } } @@ -409,6 +415,7 @@ fn generate_targets<'a>(pkg: &'a Package, } }; debug!("found {} `{}`", desc, name); + targets.push((t, profile)); } Ok(()) @@ -418,9 +425,37 @@ fn generate_targets<'a>(pkg: &'a Package, find(tests, "test", Target::is_test, test)?; find(benches, "bench", Target::is_bench, &profiles.bench)?; } - Ok(targets) + targets + } + }; + + //Collect the targets that are libraries or have all required features available. + let no_features = HashSet::new(); + let features = features.unwrap_or(&no_features); + let mut compatible_targets = Vec::with_capacity(targets.len()); + for (target, profile) in targets.drain(0..) { + if target.is_lib() || match target.required_features() { + Some(f) => !f.iter().any(|f| !features.contains(f)), + None => true, + } { + compatible_targets.push((target, profile)); + continue; + } + + if let CompileFilter::Only { .. } = *filter { + let required_features = target.required_features().unwrap(); + let quoted_required_features: Vec = required_features.iter() + .map(|s| format!("`{}`",s)) + .collect(); + bail!("target `{}` requires the features: {}\n\ + Consider enabling them by passing e.g. `--features=\"{}\"`", + target.name(), + quoted_required_features.join(", "), + required_features.join(" ")); } } + + Ok(compatible_targets) } /// Parse all config files to learn about build configuration. Currently diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index d12c73c67..c9ee9b245 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -932,6 +932,7 @@ struct TomlTarget { plugin: Option, proc_macro: Option, harness: Option, + required_features: Option>, } #[derive(RustcDecodable, Clone)] @@ -961,6 +962,7 @@ impl TomlTarget { plugin: None, proc_macro: None, harness: None, + required_features: None } } @@ -1125,7 +1127,8 @@ fn normalize(package_root: &Path, false => PathValue::Path(Path::new("src").join("main.rs")) } }); - let mut target = Target::bin_target(&bin.name(), package_root.join(path.to_path())); + let mut target = Target::bin_target(&bin.name(), package_root.join(path.to_path()), + bin.required_features.clone()); configure(bin, &mut target); dst.push(target); } @@ -1154,7 +1157,8 @@ fn normalize(package_root: &Path, let mut target = Target::example_target( &ex.name(), crate_types, - package_root.join(path.to_path()) + package_root.join(path.to_path()), + ex.required_features.clone() ); configure(ex, &mut target); dst.push(target); @@ -1169,7 +1173,8 @@ fn normalize(package_root: &Path, PathValue::Path(default(test)) }); - let mut target = Target::test_target(&test.name(), package_root.join(path.to_path())); + let mut target = Target::test_target(&test.name(), package_root.join(path.to_path()), + test.required_features.clone()); configure(test, &mut target); dst.push(target); } @@ -1183,7 +1188,8 @@ fn normalize(package_root: &Path, PathValue::Path(default(bench)) }); - let mut target = Target::bench_target(&bench.name(), package_root.join(path.to_path())); + let mut target = Target::bench_target(&bench.name(), package_root.join(path.to_path()), + bench.required_features.clone()); configure(bench, &mut target); dst.push(target); } diff --git a/tests/required-features.rs b/tests/required-features.rs new file mode 100644 index 000000000..53b504105 --- /dev/null +++ b/tests/required-features.rs @@ -0,0 +1,565 @@ +extern crate cargotest; +extern crate hamcrest; + +use cargotest::support::{project, execs}; +use hamcrest::{assert_that, existing_file, not}; + +#[test] +fn build_bin_default_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a"] + a = [] + + [[bin]] + name = "foo" + required-features = ["a"] + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), + execs().with_status(0)); + assert_that(&p.bin("foo"), existing_file()); + + assert_that(p.cargo_process("build").arg("--no-default-features"), + execs().with_status(0)); + assert_that(&p.bin("foo"), not(existing_file())); + + assert_that(p.cargo_process("build").arg("--bin=foo"), + execs().with_status(0)); + assert_that(&p.bin("foo"), existing_file()); + + assert_that(p.cargo_process("build").arg("--bin=foo").arg("--no-default-features"), + execs().with_status(101).with_stderr("\ +error: target `foo` requires the features: `a` +Consider enabling them by passing e.g. `--features=\"a\"` +")); + assert_that(&p.bin("foo"), not(existing_file())); +} + +#[test] +fn build_bin_arg_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + a = [] + + [[bin]] + name = "foo" + required-features = ["a"] + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build").arg("--features").arg("a"), + execs().with_status(0)); + assert_that(&p.bin("foo"), existing_file()); +} + +#[test] +fn build_bin_multiple_required_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[bin]] + name = "foo_1" + path = "src/foo_1.rs" + required-features = ["b", "c"] + + [[bin]] + name = "foo_2" + path = "src/foo_2.rs" + required-features = ["a"] + "#) + .file("src/foo_1.rs", "fn main() {}") + .file("src/foo_2.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), + execs().with_status(0)); + + assert_that(&p.bin("foo_1"), not(existing_file())); + assert_that(&p.bin("foo_2"), existing_file()); + + assert_that(p.cargo_process("build").arg("--features").arg("c"), + execs().with_status(0)); + + assert_that(&p.bin("foo_1"), existing_file()); + assert_that(&p.bin("foo_2"), existing_file()); + + assert_that(p.cargo_process("build").arg("--no-default-features"), + execs().with_status(0)); + + assert_that(&p.bin("foo_1"), not(existing_file())); + assert_that(&p.bin("foo_2"), not(existing_file())); +} + +#[test] +fn build_example_default_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a"] + a = [] + + [[example]] + name = "foo" + required-features = ["a"] + "#) + .file("examples/foo.rs", "fn main() {}"); + + assert_that(p.cargo_process("build").arg("--example=foo"), + execs().with_status(0)); + assert_that(&p.bin("examples/foo"), existing_file()); + + assert_that(p.cargo_process("build").arg("--example=foo").arg("--no-default-features"), + execs().with_status(101).with_stderr("\ +error: target `foo` requires the features: `a` +Consider enabling them by passing e.g. `--features=\"a\"` +")); + assert_that(&p.bin("examples/foo"), not(existing_file())); +} + +#[test] +fn build_example_arg_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + a = [] + + [[example]] + name = "foo" + required-features = ["a"] + "#) + .file("examples/foo.rs", "fn main() {}"); + + assert_that(p.cargo_process("build").arg("--example=foo").arg("--features").arg("a"), + execs().with_status(0)); + assert_that(&p.bin("examples/foo"), existing_file()); +} + +#[test] +fn build_example_multiple_required_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[example]] + name = "foo_1" + required-features = ["b", "c"] + + [[example]] + name = "foo_2" + required-features = ["a"] + "#) + .file("examples/foo_1.rs", "fn main() {}") + .file("examples/foo_2.rs", "fn main() {}"); + + assert_that(p.cargo_process("build").arg("--example=foo_1"), + execs().with_status(101).with_stderr("\ +error: target `foo_1` requires the features: `b`, `c` +Consider enabling them by passing e.g. `--features=\"b c\"` +")); + assert_that(p.cargo("build").arg("--example=foo_2"), + execs().with_status(0)); + + assert_that(&p.bin("examples/foo_1"), not(existing_file())); + assert_that(&p.bin("examples/foo_2"), existing_file()); + + assert_that(p.cargo_process("build").arg("--example=foo_1") + .arg("--features").arg("c"), + execs().with_status(0)); + assert_that(p.cargo("build").arg("--example=foo_2") + .arg("--features").arg("c"), + execs().with_status(0)); + + assert_that(&p.bin("examples/foo_1"), existing_file()); + assert_that(&p.bin("examples/foo_2"), existing_file()); + + assert_that(p.cargo_process("build").arg("--example=foo_1") + .arg("--no-default-features"), + execs().with_status(101).with_stderr("\ +error: target `foo_1` requires the features: `b`, `c` +Consider enabling them by passing e.g. `--features=\"b c\"` +")); + assert_that(p.cargo("build").arg("--example=foo_2") + .arg("--no-default-features"), + execs().with_status(101).with_stderr("\ +error: target `foo_2` requires the features: `a` +Consider enabling them by passing e.g. `--features=\"a\"` +")); + + assert_that(&p.bin("examples/foo_1"), not(existing_file())); + assert_that(&p.bin("examples/foo_2"), not(existing_file())); +} + +#[test] +fn test_default_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a"] + a = [] + + [[test]] + name = "foo" + required-features = ["a"] + "#) + .file("tests/foo.rs", "#[test]\nfn test() {}"); + + assert_that(p.cargo_process("test"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured + +")); + + assert_that(p.cargo_process("test").arg("--no-default-features"), + execs().with_status(0).with_stderr(format!("\ +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")) + .with_stdout("")); + + assert_that(p.cargo_process("test").arg("--test=foo"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured + +")); + + assert_that(p.cargo_process("test").arg("--test=foo").arg("--no-default-features"), + execs().with_status(101).with_stderr("\ +error: target `foo` requires the features: `a` +Consider enabling them by passing e.g. `--features=\"a\"` +")); +} + +#[test] +fn test_arg_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + a = [] + + [[test]] + name = "foo" + required-features = ["a"] + "#) + .file("tests/foo.rs", "#[test]\nfn test() {}"); + + assert_that(p.cargo_process("test").arg("--features").arg("a"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] target[/]debug[/]deps[/]foo-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured + +")); +} + +#[test] +fn test_multiple_required_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[test]] + name = "foo_1" + required-features = ["b", "c"] + + [[test]] + name = "foo_2" + required-features = ["a"] + "#) + .file("tests/foo_1.rs", "#[test]\nfn test() {}") + .file("tests/foo_2.rs", "#[test]\nfn test() {}"); + + assert_that(p.cargo_process("test"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] target[/]debug[/]deps[/]foo_2-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured + +")); + + assert_that(p.cargo_process("test").arg("--features").arg("c"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] target[/]debug[/]deps[/]foo_1-[..][EXE] +[RUNNING] target[/]debug[/]deps[/]foo_2-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured + + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured + +")); + + assert_that(p.cargo_process("test").arg("--no-default-features"), + execs().with_status(0).with_stderr(format!("\ +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")) + .with_stdout("")); +} + +#[test] +fn bench_default_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a"] + a = [] + + [[bench]] + name = "foo" + required-features = ["a"] + "#) + .file("benches/foo.rs", r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + }"#); + + assert_that(p.cargo_process("bench"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] release [optimized] target(s) in [..] +[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test bench ... bench: [..] 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured + +")); + + assert_that(p.cargo_process("bench").arg("--no-default-features"), + execs().with_status(0).with_stderr(format!("\ +[FINISHED] release [optimized] target(s) in [..]")) + .with_stdout("")); + + assert_that(p.cargo_process("bench").arg("--bench=foo"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] release [optimized] target(s) in [..] +[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test bench ... bench: [..] 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured + +")); + + assert_that(p.cargo_process("bench").arg("--bench=foo").arg("--no-default-features"), + execs().with_status(101).with_stderr("\ +error: target `foo` requires the features: `a` +Consider enabling them by passing e.g. `--features=\"a\"` +")); +} + +#[test] +fn bench_arg_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + a = [] + + [[bench]] + name = "foo" + required-features = ["a"] + "#) + .file("benches/foo.rs", r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + }"#); + + assert_that(p.cargo_process("bench").arg("--features").arg("a"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] release [optimized] target(s) in [..] +[RUNNING] target[/]release[/]deps[/]foo-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test bench ... bench: [..] 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured + +")); +} + +#[test] +fn bench_multiple_required_features() { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[bench]] + name = "foo_1" + required-features = ["b", "c"] + + [[bench]] + name = "foo_2" + required-features = ["a"] + "#) + .file("benches/foo_1.rs", r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + }"#) + .file("benches/foo_2.rs", r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + }"#); + + assert_that(p.cargo_process("bench"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] release [optimized] target(s) in [..] +[RUNNING] target[/]release[/]deps[/]foo_2-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test bench ... bench: [..] 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured + +")); + + assert_that(p.cargo_process("bench").arg("--features").arg("c"), + execs().with_status(0).with_stderr(format!("\ +[COMPILING] foo v0.0.1 ({}) +[FINISHED] release [optimized] target(s) in [..] +[RUNNING] target[/]release[/]deps[/]foo_1-[..][EXE] +[RUNNING] target[/]release[/]deps[/]foo_2-[..][EXE]", p.url())) + .with_stdout(" +running 1 test +test bench ... bench: [..] 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured + + +running 1 test +test bench ... bench: [..] 0 ns/iter (+/- 0) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured + +")); + + assert_that(p.cargo_process("bench").arg("--no-default-features"), + execs().with_status(0).with_stderr(format!("\ +[FINISHED] release [optimized] target(s) in [..]")) + .with_stdout("")); +} + -- 2.30.2